{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "06ac18c8-7d21-4409-a8eb-f05ea7dcfc71",
   "metadata": {},
   "source": [
    "# 第2章：NumPy基础\n",
    "\n",
    "NumPy是Python中用于科学计算的核心库，提供了高性能的多维数组对象（ndarray）以及用于处理这些数组的工具。本章将详细介绍NumPy的基础知识。\n",
    "\n",
    "## 2.1 NumPy数组的创建\n",
    "\n",
    "### 2.1.1 什么是NumPy数组？\n",
    "\n",
    "NumPy数组（ndarray）是一个多维的容器，用于存储同一类型的元素。与Python列表相比，NumPy数组具有以下优势：\n",
    "\n",
    "- 更紧凑的存储空间\n",
    "- 更快的计算速度\n",
    "- 支持向量化操作\n",
    "- 丰富的数学函数\n",
    "\n",
    "### 2.1.2 创建数组的多种方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d02030f5-4fbb-41d5-8549-3a6c434bdbcf",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.318902Z",
     "start_time": "2025-05-13T11:01:06.271863Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "从列表创建一维数组： [1 2 3 4 5]\n",
      "二维数组：\n",
      " [[1 2 3]\n",
      " [4 5 6]]\n",
      "全零数组：\n",
      " [[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n",
      "全一数组：\n",
      " [[1. 1. 1.]\n",
      " [1. 1. 1.]]\n",
      "单位矩阵：\n",
      " [[1. 0. 0. 0.]\n",
      " [0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]\n",
      " [0. 0. 0. 1.]]\n",
      "填充数组：\n",
      " [[7 7 7]\n",
      " [7 7 7]\n",
      " [7 7 7]]\n",
      "序列数组： [0 2 4 6 8]\n",
      "均匀分布数组： [0.   0.25 0.5  0.75 1.  ]\n",
      "随机数组：\n",
      " [[0.38951169 0.39394945 0.53958376]\n",
      " [0.43577403 0.22027062 0.45303934]]\n",
      "正态分布数组：\n",
      " [[-1.84973445  0.93855761 -2.02826704]\n",
      " [ 0.48810311  1.96262283 -0.38879117]\n",
      " [-0.3018375   0.53893297 -1.09020749]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# 方法1：从Python列表创建\n",
    "arr1 = np.array([1, 2, 3, 4, 5])\n",
    "print(\"从列表创建一维数组：\", arr1)\n",
    "\n",
    "# 方法2：创建二维数组\n",
    "arr2 = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "print(\"二维数组：\\n\", arr2)\n",
    "\n",
    "# 方法3：使用内置函数创建\n",
    "# 创建全零数组\n",
    "zeros_arr = np.zeros((3, 4))  # 3行4列的全零数组\n",
    "print(\"全零数组：\\n\", zeros_arr)\n",
    "\n",
    "# 创建全一数组\n",
    "ones_arr = np.ones((2, 3))  # 2行3列的全一数组\n",
    "print(\"全一数组：\\n\", ones_arr)\n",
    "\n",
    "# 创建单位矩阵\n",
    "eye_arr = np.eye(4)  # 4x4的单位矩阵\n",
    "print(\"单位矩阵：\\n\", eye_arr)\n",
    "\n",
    "# 创建指定值填充的数组\n",
    "full_arr = np.full((3, 3), 7)  # 3x3的数组，所有元素为7\n",
    "print(\"填充数组：\\n\", full_arr)\n",
    "\n",
    "# 创建序列数组\n",
    "# arange: 类似于Python的range\n",
    "range_arr = np.arange(0, 10, 2)  # 从0到10（不包含），步长为2\n",
    "print(\"序列数组：\", range_arr)\n",
    "\n",
    "# linspace: 创建均匀分布的数组\n",
    "linspace_arr = np.linspace(0, 1, 5)  # 从0到1，生成5个均匀分布的数\n",
    "print(\"均匀分布数组：\", linspace_arr)\n",
    "\n",
    "# 创建随机数组\n",
    "random_arr = np.random.random((2, 3))  # 2x3的随机数组，值在[0,1)之间\n",
    "print(\"随机数组：\\n\", random_arr)\n",
    "\n",
    "# 创建正态分布的随机数组\n",
    "normal_arr = np.random.normal(0, 1, (3, 3))  # 均值0，标准差1的3x3数组\n",
    "print(\"正态分布数组：\\n\", normal_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83a9ee50-985a-45c3-b28b-35768c26a456",
   "metadata": {},
   "source": [
    "### 2.1.3 数组的数据类型\n",
    "\n",
    "NumPy支持多种数据类型，可以在创建数组时指定："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "69827ba5-b655-41ea-82e8-6c2b1e6088a8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.403562Z",
     "start_time": "2025-05-13T11:01:06.379066Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "整型数组： [1 2 3] 类型： int32\n",
      "浮点型数组： [1. 2. 3.] 类型： float64\n",
      "复数数组： [1.+2.j 3.+4.j] 类型： complex64\n",
      "转换后的数组： [1. 2. 3.] 类型： float32\n"
     ]
    }
   ],
   "source": [
    "# 指定数据类型\n",
    "int_arr = np.array([1, 2, 3], dtype=np.int32)\n",
    "float_arr = np.array([1, 2, 3], dtype=np.float64)\n",
    "complex_arr = np.array([1+2j, 3+4j], dtype=np.complex64)\n",
    "\n",
    "print(\"整型数组：\", int_arr, \"类型：\", int_arr.dtype)\n",
    "print(\"浮点型数组：\", float_arr, \"类型：\", float_arr.dtype)\n",
    "print(\"复数数组：\", complex_arr, \"类型：\", complex_arr.dtype)\n",
    "\n",
    "# 类型转换\n",
    "converted_arr = int_arr.astype(np.float32)\n",
    "print(\"转换后的数组：\", converted_arr, \"类型：\", converted_arr.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11a87d6b-8ea2-4b00-a5d1-cee0f18c4207",
   "metadata": {},
   "source": [
    "## 2.2 数组的属性\n",
    "\n",
    "了解数组的属性是掌握NumPy的基础："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a2a08294-87c2-46f7-a77b-b4ac9183e13d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(float_arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "fa0136a0-8ccc-470c-ae23-e1270d4cd4ad",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.446448Z",
     "start_time": "2025-05-13T11:01:06.442110Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组形状 (shape)： (3, 4)\n",
      "数组维度 (ndim)： 2\n",
      "数组元素总数 (size)： 12\n",
      "数组数据类型 (dtype)： int64\n",
      "每个元素字节大小 (itemsize)： 8\n",
      "数组总字节数 (nbytes)： 96\n",
      "数组内存信息：   C_CONTIGUOUS : True\n",
      "  F_CONTIGUOUS : False\n",
      "  OWNDATA : True\n",
      "  WRITEABLE : True\n",
      "  ALIGNED : True\n",
      "  WRITEBACKIFCOPY : False\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 创建一个示例数组\n",
    "arr = np.array([[1, 2, 3, 4],\n",
    "                [5, 6, 7, 8],\n",
    "                [9, 10, 11, 12]])\n",
    "\n",
    "# 基本属性\n",
    "print(\"数组形状 (shape)：\", arr.shape)  # (3, 4) 表示3行4列\n",
    "print(\"数组维度 (ndim)：\", arr.ndim)   # 2 表示二维数组\n",
    "print(\"数组元素总数 (size)：\", arr.size)  # 12 个元素\n",
    "print(\"数组数据类型 (dtype)：\", arr.dtype)  # 数据类型\n",
    "print(\"每个元素字节大小 (itemsize)：\", arr.itemsize)  # 字节数\n",
    "\n",
    "# 内存相关信息\n",
    "print(\"数组总字节数 (nbytes)：\", arr.nbytes)  # size * itemsize\n",
    "print(\"数组内存信息：\", arr.flags)  # 显示内存布局等信息"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f425d359-2345-49db-8e08-64c113c48416",
   "metadata": {},
   "source": [
    "## 2.3 数组的索引和切片\n",
    "\n",
    "### 2.3.1 一维数组的索引和切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "ee89eb99-4855-4f5a-9792-fa33df2b8753",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.461571Z",
     "start_time": "2025-05-13T11:01:06.456756Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一个元素： 10\n",
      "最后一个元素： 90\n",
      "第三个元素： 30\n",
      "前三个元素： [10 20 30]\n",
      "从第三个到第六个： [30 40 50 60]\n",
      "从第三个到最后： [30 40 50 60 70 80 90]\n",
      "倒数三个元素： [70 80 90]\n",
      "步长为2的切片： [10 30 50 70 90]\n",
      "逆序： [90 80 70 60 50 40 30 20 10]\n",
      "修改后的数组： [100  20  30  40  50  60  70  80  90]\n",
      "批量修改后： [100  20  30 999 999 999  70  80  90]\n"
     ]
    }
   ],
   "source": [
    "# 创建一维数组\n",
    "arr_1d = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90])\n",
    "\n",
    "# 基本索引\n",
    "print(\"第一个元素：\", arr_1d[0])\n",
    "print(\"最后一个元素：\", arr_1d[-1])\n",
    "print(\"第三个元素：\", arr_1d[2])\n",
    "\n",
    "# 切片操作\n",
    "print(\"前三个元素：\", arr_1d[:3])\n",
    "print(\"从第三个到第六个：\", arr_1d[2:6])\n",
    "print(\"从第三个到最后：\", arr_1d[2:])\n",
    "print(\"倒数三个元素：\", arr_1d[-3:])\n",
    "print(\"步长为2的切片：\", arr_1d[::2])\n",
    "print(\"逆序：\", arr_1d[::-1])\n",
    "\n",
    "# 修改元素\n",
    "arr_1d[0] = 100\n",
    "print(\"修改后的数组：\", arr_1d)\n",
    "\n",
    "# 批量修改\n",
    "arr_1d[3:6] = 999\n",
    "print(\"批量修改后：\", arr_1d)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14d23c34-311a-4f12-8f81-d2837dba26c7",
   "metadata": {},
   "source": [
    "2.3.2 二维数组的索引和切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b3fa91db-c384-4579-ad01-777c742fabe3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.504770Z",
     "start_time": "2025-05-13T11:01:06.499439Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一行第二列： 2\n",
      "第三行第四列： 12\n",
      "第一行： [1 2 3 4]\n",
      "第一行和第二行：\n",
      " [[1 2 3 4]\n",
      " [5 6 7 8]]\n",
      "第一列： [ 1  5  9 13]\n",
      "第二列和第三列：\n",
      " [[ 2  3]\n",
      " [ 6  7]\n",
      " [10 11]\n",
      " [14 15]]\n",
      "左上角2x2区域：\n",
      " [[1 2]\n",
      " [5 6]]\n",
      "右下角2x2区域：\n",
      " [[11 12]\n",
      " [15 16]]\n",
      "隔行隔列选取：\n",
      " [[ 1  3]\n",
      " [ 9 11]]\n",
      "修改后的数组：\n",
      " [[ 1  2  3  4]\n",
      " [ 5  0  0  8]\n",
      " [ 9  0  0 12]\n",
      " [13 14 15 16]]\n"
     ]
    }
   ],
   "source": [
    "# 创建二维数组\n",
    "arr_2d = np.array([[1, 2, 3, 4],\n",
    "                   [5, 6, 7, 8],\n",
    "                   [9, 10, 11, 12],\n",
    "                   [13, 14, 15, 16]])\n",
    "\n",
    "# 基本索引\n",
    "print(\"第一行第二列：\", arr_2d[0, 1])  # 或 arr_2d[0][1]\n",
    "print(\"第三行第四列：\", arr_2d[2, 3])\n",
    "\n",
    "# 行切片\n",
    "print(\"第一行：\", arr_2d[0])\n",
    "print(\"第一行和第二行：\\n\", arr_2d[0:2])\n",
    "\n",
    "# 列切片\n",
    "print(\"第一列：\", arr_2d[:, 0])\n",
    "print(\"第二列和第三列：\\n\", arr_2d[:, 1:3])\n",
    "\n",
    "# 区域切片\n",
    "print(\"左上角2x2区域：\\n\", arr_2d[:2, :2])\n",
    "print(\"右下角2x2区域：\\n\", arr_2d[2:, 2:])\n",
    "\n",
    "# 步长切片\n",
    "print(\"隔行隔列选取：\\n\", arr_2d[::2, ::2])\n",
    "\n",
    "# 修改区域\n",
    "arr_2d[1:3, 1:3] = 0\n",
    "print(\"修改后的数组：\\n\", arr_2d)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f78ce4fa-f152-4b0e-8782-31301f5876b4",
   "metadata": {},
   "source": [
    "2.3.3 布尔索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "bc68253d-fef6-474a-8b6e-08b708a04fc8",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.540052Z",
     "start_time": "2025-05-13T11:01:06.536937Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "布尔掩码： [False False False False  True  True  True]\n",
      "大于25的元素： [30 35 40]\n",
      "大于25的元素（直接写法）： [30 35 40]\n",
      "大于20且小于35的元素： [25 30]\n",
      "修改后的数组： [ 10  15  20  25  30 999 999]\n",
      "二维数组中大于5的元素： [6 7 8 9]\n",
      "修改后的二维数组：\n",
      " [[1 0 3]\n",
      " [0 5 0]\n",
      " [7 0 9]]\n"
     ]
    }
   ],
   "source": [
    "# 创建示例数组\n",
    "arr = np.array([10, 15, 20, 25, 30, 35, 40])\n",
    "\n",
    "# 创建布尔条件\n",
    "mask = arr > 25\n",
    "print(\"布尔掩码：\", mask)\n",
    "\n",
    "# 使用布尔索引选择元素\n",
    "print(\"大于25的元素：\", arr[mask])\n",
    "print(\"大于25的元素（直接写法）：\", arr[arr > 25])\n",
    "\n",
    "# 复合条件\n",
    "print(\"大于20且小于35的元素：\", arr[(arr > 20) & (arr < 35)])\n",
    "\n",
    "# 布尔索引修改值\n",
    "arr[arr > 30] = 999\n",
    "print(\"修改后的数组：\", arr)\n",
    "\n",
    "# 二维数组的布尔索引\n",
    "arr_2d = np.array([[1, 2, 3],\n",
    "                   [4, 5, 6],\n",
    "                   [7, 8, 9]])\n",
    "\n",
    "# 选择大于5的元素\n",
    "print(\"二维数组中大于5的元素：\", arr_2d[arr_2d > 5])\n",
    "\n",
    "# 条件修改\n",
    "arr_2d[arr_2d % 2 == 0] = 0  # 将偶数改为0\n",
    "print(\"修改后的二维数组：\\n\", arr_2d)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f17351e4-33e9-45b6-adf3-ee9c3fed9a7c",
   "metadata": {},
   "source": [
    "2.3.4 花式索引（Fancy Indexing）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "264da2aa-5b23-4da6-8853-045fbe4d6000",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.554330Z",
     "start_time": "2025-05-13T11:01:06.551739Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "指定位置的元素： [20 40 60 80]\n",
      "原始数组：\n",
      " [[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]\n",
      " [12 13 14 15]]\n",
      "选择的元素： [ 1  6 15]\n",
      "网格选择：\n",
      " [[ 1  3]\n",
      " [ 9 11]]\n"
     ]
    }
   ],
   "source": [
    "# 创建示例数组\n",
    "arr = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90])\n",
    "\n",
    "# 使用整数数组索引\n",
    "indices = [1, 3, 5, 7]\n",
    "print(\"指定位置的元素：\", arr[indices])\n",
    "\n",
    "# 多个索引数组\n",
    "arr_2d = np.arange(16).reshape(4, 4)\n",
    "print(\"原始数组：\\n\", arr_2d)\n",
    "\n",
    "# 选择特定的行和列\n",
    "rows = [0, 1, 3]\n",
    "cols = [1, 2, 3]\n",
    "print(\"选择的元素：\", arr_2d[rows, cols])  # 选择(0,1), (1,2), (3,3)\n",
    "\n",
    "# 使用ix_函数创建网格\n",
    "rows = np.array([0, 2])\n",
    "cols = np.array([1, 3])\n",
    "print(\"网格选择：\\n\", arr_2d[np.ix_(rows, cols)])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f4e4ede-a645-4e91-89e4-049a7498f21d",
   "metadata": {},
   "source": [
    "## 2.4 数组的形状操作\n",
    "\n",
    "### 2.4.1 改变数组形状"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f34255dc-55ac-4a2e-9835-7d944289016a",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.562235Z",
     "start_time": "2025-05-13T11:01:06.559950Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组： [ 0  1  2  3  4  5  6  7  8  9 10 11]\n",
      "改变为3x4：\n",
      " [[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "自动推断列数：\n",
      " [[ 0  1  2  3  4  5]\n",
      " [ 6  7  8  9 10 11]]\n",
      "resize后的数组：\n",
      " [[ 0  1  2  3  4  5]\n",
      " [ 6  7  8  9 10 11]]\n",
      "展平后： [1 2 3 4 5 6]\n",
      "flatten结果： [1 2 3 4 5 6]\n"
     ]
    }
   ],
   "source": [
    "# 创建一维数组\n",
    "arr = np.arange(12)\n",
    "print(\"原始数组：\", arr)\n",
    "\n",
    "# reshape：改变形状（不修改原数组）\n",
    "reshaped = arr.reshape(3, 4)\n",
    "print(\"改变为3x4：\\n\", reshaped)\n",
    "\n",
    "# 自动推断维度\n",
    "auto_shape = arr.reshape(2, -1)  # -1表示自动计算\n",
    "print(\"自动推断列数：\\n\", auto_shape)\n",
    "\n",
    "# resize：改变形状（修改原数组）\n",
    "arr_copy = arr.copy()\n",
    "arr_copy.resize(2, 6)\n",
    "print(\"resize后的数组：\\n\", arr_copy)\n",
    "\n",
    "# ravel：展平数组\n",
    "arr_2d = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "flattened = arr_2d.ravel()\n",
    "print(\"展平后：\", flattened)\n",
    "\n",
    "# flatten：展平数组（返回副本）\n",
    "flattened_copy = arr_2d.flatten()\n",
    "print(\"flatten结果：\", flattened_copy)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbe698df-5d27-4ea5-b7e4-0b422cbd9cc6",
   "metadata": {},
   "source": [
    "2.4.2 转置和轴交换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "167ef5fe-09f1-4c04-b009-09d62a9b9192",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.568762Z",
     "start_time": "2025-05-13T11:01:06.566583Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组：\n",
      " [[1 2 3]\n",
      " [4 5 6]]\n",
      "转置后：\n",
      " [[1 4]\n",
      " [2 5]\n",
      " [3 6]]\n",
      "transpose方法：\n",
      " [[1 4]\n",
      " [2 5]\n",
      " [3 6]]\n",
      "原始三维数组形状： (2, 3, 4)\n",
      "交换第0轴和第2轴后的形状： (4, 3, 2)\n",
      "重新排列轴后的形状： (3, 4, 2)\n"
     ]
    }
   ],
   "source": [
    "# 创建二维数组\n",
    "arr_2d = np.array([[1, 2, 3],\n",
    "                   [4, 5, 6]])\n",
    "print(\"原始数组：\\n\", arr_2d)\n",
    "\n",
    "# 转置\n",
    "transposed = arr_2d.T\n",
    "print(\"转置后：\\n\", transposed)\n",
    "\n",
    "# 使用transpose方法\n",
    "transposed2 = np.transpose(arr_2d)\n",
    "print(\"transpose方法：\\n\", transposed2)\n",
    "\n",
    "# 三维数组的轴交换\n",
    "arr_3d = np.arange(24).reshape(2, 3, 4)\n",
    "print(\"原始三维数组形状：\", arr_3d.shape)\n",
    "\n",
    "# 交换轴\n",
    "swapped = np.swapaxes(arr_3d, 0, 2)\n",
    "print(\"交换第0轴和第2轴后的形状：\", swapped.shape)\n",
    "\n",
    "# 使用transpose指定轴顺序\n",
    "reordered = arr_3d.transpose(1, 2, 0)\n",
    "print(\"重新排列轴后的形状：\", reordered.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cf7d8fe-28ea-4efc-9852-2da36c96147a",
   "metadata": {},
   "source": [
    "2.4.3 数组的合并和分割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "871d388f-7296-4cf8-b8bf-5716d00152ce",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.578013Z",
     "start_time": "2025-05-13T11:01:06.574854Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "垂直合并：\n",
      " [[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]]\n",
      "水平合并：\n",
      " [[1 2 5 6]\n",
      " [3 4 7 8]]\n",
      "沿axis=0合并：\n",
      " [[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]]\n",
      "沿axis=1合并：\n",
      " [[1 2 5 6]\n",
      " [3 4 7 8]]\n",
      "原始数组：\n",
      " [[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]\n",
      " [12 13 14 15]]\n",
      "垂直分割结果：\n",
      "部分1：\n",
      " [[0 1 2 3]\n",
      " [4 5 6 7]]\n",
      "部分2：\n",
      " [[ 8  9 10 11]\n",
      " [12 13 14 15]]\n",
      "水平分割结果：\n",
      "部分1：\n",
      " [[ 0  1]\n",
      " [ 4  5]\n",
      " [ 8  9]\n",
      " [12 13]]\n",
      "部分2：\n",
      " [[ 2  3]\n",
      " [ 6  7]\n",
      " [10 11]\n",
      " [14 15]]\n",
      "指定位置分割：\n",
      "部分1：\n",
      " [[0 1 2 3]]\n",
      "部分2：\n",
      " [[ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "部分3：\n",
      " [[12 13 14 15]]\n"
     ]
    }
   ],
   "source": [
    "# 合并操作\n",
    "# 创建示例数组\n",
    "a = np.array([[1, 2], [3, 4]])\n",
    "b = np.array([[5, 6], [7, 8]])\n",
    "\n",
    "# 垂直合并（沿着行）\n",
    "v_stack = np.vstack((a, b))\n",
    "print(\"垂直合并：\\n\", v_stack)\n",
    "\n",
    "# 水平合并（沿着列）\n",
    "h_stack = np.hstack((a, b))\n",
    "print(\"水平合并：\\n\", h_stack)\n",
    "\n",
    "# concatenate：通用合并函数\n",
    "concat_axis0 = np.concatenate((a, b), axis=0)  # 沿着第0轴（行）\n",
    "concat_axis1 = np.concatenate((a, b), axis=1)  # 沿着第1轴（列）\n",
    "print(\"沿axis=0合并：\\n\", concat_axis0)\n",
    "print(\"沿axis=1合并：\\n\", concat_axis1)\n",
    "\n",
    "# 分割操作\n",
    "arr = np.arange(16).reshape(4, 4)\n",
    "print(\"原始数组：\\n\", arr)\n",
    "\n",
    "# 垂直分割\n",
    "v_split = np.vsplit(arr, 2)  # 分成2部分\n",
    "print(\"垂直分割结果：\")\n",
    "for i, sub_arr in enumerate(v_split):\n",
    "    print(f\"部分{i+1}：\\n\", sub_arr)\n",
    "\n",
    "# 水平分割\n",
    "h_split = np.hsplit(arr, 2)  # 分成2部分\n",
    "print(\"水平分割结果：\")\n",
    "for i, sub_arr in enumerate(h_split):\n",
    "    print(f\"部分{i+1}：\\n\", sub_arr)\n",
    "\n",
    "# 指定位置分割\n",
    "split_indices = np.split(arr, [1, 3], axis=0)  # 在第1行和第3行处分割\n",
    "print(\"指定位置分割：\")\n",
    "for i, sub_arr in enumerate(split_indices):\n",
    "    print(f\"部分{i+1}：\\n\", sub_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b092f1f1-69c2-454d-ab78-0cadf2fbad68",
   "metadata": {},
   "source": [
    "## 2.5 数组的复制与视图\n",
    "\n",
    "理解NumPy中的视图和副本非常重要，这关系到内存效率和数据安全："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "fa0845b8-8c11-4006-99ed-ca9fc916d369",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.586871Z",
     "start_time": "2025-05-13T11:01:06.584371Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "修改引用后的原始数组： [999   2   3   4   5]\n",
      "修改视图后的原始数组： [888   2   3   4   5]\n",
      "视图的id： 5095130672\n",
      "原始数组的id： 5094899024\n",
      "修改切片后的原始数组： [  1 777   3   4   5]\n",
      "修改副本后的原始数组： [1 2 3 4 5]\n",
      "副本： [666   2   3   4   5]\n",
      "视图共享内存： False\n",
      "副本共享内存： False\n"
     ]
    }
   ],
   "source": [
    "# 创建原始数组\n",
    "original = np.array([1, 2, 3, 4, 5])\n",
    "\n",
    "# 赋值操作（创建引用）\n",
    "reference = original\n",
    "reference[0] = 999\n",
    "print(\"修改引用后的原始数组：\", original)  # 原始数组也被修改\n",
    "\n",
    "# 视图（浅拷贝）\n",
    "original = np.array([1, 2, 3, 4, 5])\n",
    "view = original.view()\n",
    "view[0] = 888\n",
    "print(\"修改视图后的原始数组：\", original)  # 原始数组被修改\n",
    "print(\"视图的id：\", id(view))\n",
    "print(\"原始数组的id：\", id(original))\n",
    "\n",
    "# 切片创建视图\n",
    "original = np.array([1, 2, 3, 4, 5])\n",
    "slice_view = original[1:4]\n",
    "slice_view[0] = 777\n",
    "print(\"修改切片后的原始数组：\", original)  # 原始数组被修改\n",
    "\n",
    "# 副本（深拷贝）\n",
    "original = np.array([1, 2, 3, 4, 5])\n",
    "copy = original.copy()\n",
    "copy[0] = 666\n",
    "print(\"修改副本后的原始数组：\", original)  # 原始数组不变\n",
    "print(\"副本：\", copy)\n",
    "\n",
    "# 检查是否共享内存\n",
    "print(\"视图共享内存：\", np.shares_memory(original, view))\n",
    "print(\"副本共享内存：\", np.shares_memory(original, copy))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a7335b86-a399-4ab8-997a-50b820288a64",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "修改引用后的原始数组： [999   2   3   4   5]\n"
     ]
    }
   ],
   "source": [
    "original = np.array([1, 2, 3, 4, 5])\n",
    "\n",
    "# 赋值操作（创建引用）\n",
    "reference = original\n",
    "reference[0] = 999\n",
    "print(\"修改引用后的原始数组：\", original)  # 原始数组也被修改"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4402c31b-d47b-48bc-b1e6-b9b523d0ab0c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-13T11:01:06.593705Z",
     "start_time": "2025-05-13T11:01:06.592581Z"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
